package be.tihh.mgmt.gui.tree;

import be.tihh.mgmt.gui.MainScreen;
import be.tihh.mgmt.gui.icontreenode.ComputerIcons;
import be.tihh.mgmt.gui.icontreenode.IconNode;
import be.tihh.mgmt.gui.icontreenode.IconNodeRenderer;
import be.tihh.mgmt.gui.util.IconFactory;
import be.tihh.mgmt.gui.xml.computers.Computer;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.swing.*;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class GuiTreeBuilder {

    private DefaultTreeModel model;
    public static final String FLOPPY_DRIVE_ICON = "FLOPPY_DRIVE";
    public static final String HARD_DRIVE_ICON = "HARD_DRIVE";
    public static final String FOLDER_ICON = "FOLDER";
    public static final String COMPUTER_ICON = "COMPUTER";
    public static final String C_TEXT_ICON = "C_TEXT";
    public static final String JAVA_TEXT_ICON = "JAVA_TEXT";
    public static final String HTML_TEXT_ICON = "HTML_TEXT";
    private ExecutorService guiTreeExecutorService;

    public JTree buildTree(final Node original, final MainScreen mainScreen) {

        guiTreeExecutorService = Executors.newCachedThreadPool();

        JTree tree = mainScreen.getTree();
        tree.putClientProperty("JTree.icons", makeIcons());
        tree.setCellRenderer(new IconNodeRenderer());

        String rootName = "computers";
        NodeList childNodes = original.getChildNodes();
        int length = childNodes.getLength();
        for (int i = 0; i < length; i++) {
            Node child = childNodes.item(i);
            String nodeName = child.getNodeName();
            if ("dir".equals(nodeName)) {
                NamedNodeMap attributes = child.getAttributes();
                String path = attributes.getNamedItem("path").getNodeValue();
                rootName = "" + path.charAt(0);
                break;
            }
        }


        model = (DefaultTreeModel) tree.getModel();
        //todo : startNode is static -> get from xml (?)
        IconNode startNode = new IconNode(rootName);
        model.setRoot(startNode);

        //Where the tree is initialized:
        tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);

        tree.addTreeExpansionListener(
                new TreeExpansionListener() {
                    public void treeExpanded(TreeExpansionEvent event) {
                        TreePath path = event.getPath();
                        IconNode node = (IconNode) path.getLastPathComponent();
                        Enumeration children = node.children();
                        while (children.hasMoreElements()) {
                            IconNode childNode = (IconNode)children.nextElement();
                            //if computer icon, start thread to see if computer is online
                            if(childNode.getIconName().startsWith(ComputerIcons.PREFIX)){
                                guiTreeExecutorService.submit(new SelectComputerAction(childNode, mainScreen));
                            }
                        }
                    }

                    public void treeCollapsed(TreeExpansionEvent event) {
                    }
                }
        );

        //Listen for when the selection changes.
        tree.addTreeSelectionListener(
                new TreeSelectionListener() {

                    public void valueChanged(TreeSelectionEvent e) {
                        IconNode node = (IconNode) e.getPath().getLastPathComponent();
                        guiTreeExecutorService.submit(new SelectComputerAction(node, mainScreen));
                    }

                }
        );

        addGuiTreeNodes(original, startNode);

        // add MouseListener to tree
        MouseAdapter ma = new MouseAdapter() {
            private void myPopupEvent(MouseEvent e) {
                int x = e.getX();
                int y = e.getY();
                JTree tree = (JTree)e.getSource();
                TreePath path = tree.getPathForLocation(x, y);
                if (path == null)
                    return;

                tree.setSelectionPath(path);

                IconNode rightClickedNode = (IconNode)path.getLastPathComponent();

                if(rightClickedNode.isLeaf()){
                    JPopupMenu popup = new JPopupMenu();
                    final TreeMenuItem refreshMenuItem = new TreeMenuItem("refresh", IconFactory.getIcon(IconFactory.REFRESH), rightClickedNode);
                    refreshMenuItem.addActionListener(new ActionListener(){
                        @Override
                        public void actionPerformed(ActionEvent actionEvent) {
                            guiTreeExecutorService.submit(new SelectComputerAction(refreshMenuItem.getSelectedNode(), mainScreen));
                        }
                    });
                    popup.add(refreshMenuItem);
                    popup.show(tree, x, y);
                }
            }
            public void mousePressed(MouseEvent e) {
                if (e.isPopupTrigger()) myPopupEvent(e);
            }
            public void mouseReleased(MouseEvent e) {
                if (e.isPopupTrigger()) myPopupEvent(e);
            }
        };

        tree.addMouseListener(ma);


/*
        //expand all
        int row = 0;
        while (row < tree.getRowCount()) {
            tree.expandRow(row);
            row++;
        }
*/
        //Expand "Computers" node
        tree.expandRow(0);

        return tree;
    }

    private void addGuiTreeNodes(Node originalXmlNode, IconNode originalTreeNode) {
        NodeList childNodes = originalXmlNode.getChildNodes();
        int length = childNodes.getLength();
        for (int i = 0; i < length; i++) {
            Node child = childNodes.item(i);
            String nodeName = child.getNodeName();
            if ("folder".equals(nodeName)) {
                //get name
                NamedNodeMap attributes = child.getAttributes();
                String folderName = attributes.getNamedItem("name").getNodeValue();

                // Create new node
                IconNode newTreeNode = new IconNode(folderName);
                newTreeNode.setIconName(FOLDER_ICON);
                // Insert new node as last child of node
                model.insertNodeInto(newTreeNode, originalTreeNode, originalTreeNode.getChildCount());

                addGuiTreeNodes(child, newTreeNode);
            } else if ("computer".equals(nodeName)) {
//                String fileName = ((Element) child).getAttribute("name");
                String computerId = "n/a";
                String computerName = "n/a";
                String computerMacAddress = "n/a";
                NodeList computerNodes = child.getChildNodes();
                for (int j = 0; j < computerNodes.getLength(); j++) {
                    Node node = computerNodes.item(j);
                    if ("name".equals(node.getNodeName())) computerName = node.getFirstChild().getNodeValue();
                    if ("id".equals(node.getNodeName())) computerId = node.getFirstChild().getNodeValue();
                    if ("macaddress".equals(node.getNodeName()))
                        computerMacAddress = node.getFirstChild().getNodeValue();
                }
                Computer computer = new Computer();
                computer.setId(computerId);
                computer.setName(computerName);
                computer.setMacAddress(computerMacAddress);
                IconNode newTreeNode = new IconNode(computer);
                newTreeNode.setIconName(ComputerIcons.COMPUTER_STATUS_UNKNOWN);
                model.insertNodeInto(newTreeNode, originalTreeNode, originalTreeNode.getChildCount());
            }
        }
    }

    private Hashtable<String, Icon> makeIcons() {
        Hashtable<String, Icon> icons = new Hashtable<String, Icon>();
        icons.put(FOLDER_ICON, new ImageIcon("res\\icons\\folder.png"));
        icons.put(ComputerIcons.COMPUTER_STATUS_ON, new ImageIcon("res\\icons\\computer_on.png"));
        icons.put(ComputerIcons.COMPUTER_STATUS_OFF, new ImageIcon("res\\icons\\computer_off.png"));
        icons.put(ComputerIcons.COMPUTER_STATUS_UNKNOWN, new ImageIcon("res\\icons\\computer.png"));
        return icons;
    }


}
